package com.hippo.gateway.listener;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.client.naming.event.InstancesChangeEvent;
import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.notify.listener.Subscriber;
import com.alibaba.nacos.common.utils.CollectionUtils;
import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springdoc.core.properties.AbstractSwaggerUiConfigProperties;
import org.springdoc.core.properties.SwaggerUiConfigProperties;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.route.CachingRouteLocator;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.stereotype.Component;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * @ClassName InstancesChangeEventListener
 * @Description TODO 动态刷新Swagger下拉
 * @Author tangxl
 * @create 2023-03-30 10:20
 **/
@Component
public class InstancesChangeEventListener extends Subscriber<InstancesChangeEvent> implements InitializingBean {

    private static final Logger logger = LoggerFactory.getLogger(InstancesChangeEventListener.class);

    @Autowired
    private RouteLocator routeLocator;
    @Autowired
    private SwaggerUiConfigProperties swaggerUiConfigProperties;
    @Value("${spring.application.name}")
    private String applicationName;

    private Set<AbstractSwaggerUiConfigProperties.SwaggerUrl> urls;

    @PostConstruct
    private void post() {
        NotifyCenter.registerSubscriber(this);
    }


    /**
     * Event callback.
     *
     * @param event {@link Event}
     */
    @Override
    public void onEvent(InstancesChangeEvent event) {
        logger.info("接收到 InstancesChangeEvent 订阅事件：{}", JSON.toJSONString(event));

        CachingRouteLocator cachingRouteLocator = (CachingRouteLocator) routeLocator;
        cachingRouteLocator.refresh();

        List<Route> routeList = routeLocator.getRoutes().collectList().block();

        System.out.println(routeList);

        LinkedHashSet<AbstractSwaggerUiConfigProperties.SwaggerUrl> set = new LinkedHashSet<>();

        if (CollectionUtils.isNotEmpty(this.urls)) {
            set.addAll(this.urls);
        }

        for (Route route : routeList) {
            if (route.getMetadata().size() > 0) {
                // ReactiveCompositeDiscoveryClient_sky-user
                String id = route.getId();
                String name = id.replaceAll("ReactiveCompositeDiscoveryClient_", "");
                if (applicationName.equals(name)) {
                    continue;
                }
                set.add(new AbstractSwaggerUiConfigProperties.SwaggerUrl(name, "/"+name+"/v3/api-docs", ""));
            }
        }

        if (CollectionUtils.isEmpty(set)) {
            set.add(new AbstractSwaggerUiConfigProperties.SwaggerUrl("_default", "/v3/api-docs/_default", ""));
        }

        swaggerUiConfigProperties.setUrls(set);

    }

    /**
     * Type of this subscriber's subscription.
     *
     * @return Class which extends {@link Event}
     */
    @Override
    public Class<? extends com.alibaba.nacos.common.notify.Event> subscribeType() {
        return InstancesChangeEvent.class;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.urls = this.swaggerUiConfigProperties.getUrls();
    }
}
